package com.cn.common.utils.uuid;

import java.net.InetAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.cn.common.utils.exception.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GUID {
    private static final Logger logger = LoggerFactory.getLogger(GUID.class);
    private static final Map<String, GUID> BEAN_MAP = new ConcurrentHashMap();
    private static final long BEGIN_TS = 1483200000000L;
    private long lastTs = 0L;
    private long processId;
    private int processIdBits = 10;
    private long sequence = 0L;
    private int sequenceBits = 10;

    public GUID(long processId) {
        if (processId > (long)((1 << this.processIdBits) - 1)) {
            throw new ServiceException("设置位数" + this.processIdBits + ",最大" + ((1 << this.processIdBits) - 1));
        } else {
            this.processId = processId;
        }
    }

    protected long timeGen() {
        return System.currentTimeMillis();
    }

    public synchronized long nextId() {
        long ts = this.timeGen();
        if (ts < this.lastTs) {
            throw new ServiceException("时间戳顺序错误");
        } else {
            if (ts == this.lastTs) {
                this.sequence = this.sequence + 1L & (long)((1 << this.sequenceBits) - 1);
                if (this.sequence == 0L) {
                    ts = this.nextTs(this.lastTs);
                }
            } else {
                this.sequence = 0L;
            }

            this.lastTs = ts;
            return ts - 1483200000000L << this.processIdBits + this.sequenceBits | this.processId << this.sequenceBits | this.sequence;
        }
    }

    protected long nextTs(long lastTs) {
        long ts;
        for(ts = this.timeGen(); ts <= lastTs; ts = this.timeGen()) {
        }

        return ts;
    }

    public static synchronized GUID getInstance() {
        GUID idGenerator = null;
        String hostName = null;

        try {
            hostName = InetAddress.getLocalHost().getHostName();
            String currentIpAddress = InetAddress.getByName(hostName).getHostAddress();
            String endIp = currentIpAddress.substring(currentIpAddress.lastIndexOf(".") + 1);
            if (BEAN_MAP.containsKey(endIp)) {
                return (GUID)BEAN_MAP.get(endIp);
            } else {
                int processId = Integer.parseInt(endIp);
                idGenerator = new GUID((long)processId);
                BEAN_MAP.put(endIp, idGenerator);
                return idGenerator;
            }
        } catch (Exception var5) {
            logger.error(var5.getMessage());
            if (BEAN_MAP.containsKey("1024")) {
                return (GUID)BEAN_MAP.get("1024");
            } else {
                idGenerator = new GUID(1024L);
                BEAN_MAP.put("1024", idGenerator);
                return idGenerator;
            }
        }
    }

}